<!DOCTYPE html>
<html lang="zh-CN">

<head>
	<meta charset="utf-8">
	<title>个人账户信息管理</title>
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">
	<!-- <link href="css/bootstrap.min.css" rel="stylesheet"> -->
	<!-- <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-icons/1.8.3/font/bootstrap-icons.min.css" rel="stylesheet"> -->
	<!-- <link href="css/bootstrap-icons.min.css" rel="stylesheet"> -->
	<style>
		html, body, .full-height { height: 100%;}
		.input-width { width: 200px; }
		.header-background-color { background-color: #C8E6C9; }
		.edit-label-width { width: 70px; }
		.edit-ctrl-width { width: 100%; }
	</style>
</head>

<body>
	<div id="app" class="full-height">

		<!-- 主页面 -->
		<div v-if="showPage=='home'" class="container-fluid">
			<div class="row header-background-color p-2 bg-gradient">
				<div class="col d-flex align-items-center">
					<h4>个人账户信息管理</h4>
				</div>
				<div class="col d-flex justify-content-end align-items-center">
					<button type="button" @click="logout" class="btn btn-link btn-sm">退出</button>
				</div>
			</div>
			<div class="row">
				<div class="col d-flex justify-content-start p-2">
					<input v-model="findStr" @keyup.enter="search"
						class="form-control form-control-sm input-width" type="text"
						placeholder="标题/账号/备注" autofocus="autofocus"/>
					<button @click="search" type="button" class="form-control-smbtn btn-primary rounded mx-2">查询</button>
					<button @click="edit()" type="button" class="form-control-smbtn btn-success rounded">新增</button>
				</div>
				<div class="col d-flex justify-content-end p-2">
					<button @click="del" type="button" class="form-control-smbtn btn-danger rounded mx-2">删除</button>
				</div>
			</div>
			<div class="row p-2">
				<table class="table table-bordered table-striped table-sm" style="word-break:break-all; word-wrap:break-all;">
					<thead class="table-light">
						<tr>
							<th style="width: 24px"></th>
							<th scope="col" class="text-primary">标题</th>
							<th scope="col" class="text-success">用户名</th>
							<th scope="col" class="text-danger">密码</th>
							<th scope="col" class="text-info">网址</th>
						</tr>
						<tr>
							<th scope="col" colspan="4" style="text-align: center;">备注</th>
						</tr>
					</thead>
					<tbody>
						<template v-for="(rec, idx) in records">
							<tr :key="rec.id">
								<td><input class="form-check-input" type="checkbox" v-model="rec.checked"></td>
								<td class="text-primary"><a href="javascript:void(0)" @click="edit(rec)">{{rec.title}}</a></td>
								<td class="text-success">{{rec.user}}</td>
								<td class="text-danger">{{rec.pass}}</td>
								<td class="text-info">{{rec.url}}</td>
							</tr>
							<tr :key="rec.id + '_'">
								<td class="text-wrap" colspan="4">{{rec.memo}}<span v-if="!rec.memo">&nbsp;</span></td>
							</tr>
						</template>
					</tbody>
				</table>
			</div>
		</div><!-- 主页面 -->

		<!-- 登录页面 -->
		<div v-if="showPage=='login'" class="container full-height">
			<div class="d-flex flex-column align-items-center justify-content-center full-height">
				<div>
					<h5 class="text-center">个人账户管理系统</h5>
					<h6 class="text-center text-primary">用户登录</h6>
				</div>
				<form class="p-3 border bg-light">
					<div class="form-group">
						<input :class="{'is-invalid': !usernameChecked}" v-model="username" @keyup.enter="nextFocus"
							class="form-control input-width mx-auto" type="text"
							placeholder="请输入用户名" autofocus="autofocus" />
						<p class="invalid-feedback" style="display: block;" :style="{visibility: usernameStyle}">必须输入用户名</p>
					</div>
					<div class="form-group">
						<input :class="{'is-invalid': !passwordChecked}" v-model="password" @keyup.enter="login"
							class="form-control input-width mx-auto" type="password" placeholder="请输入密码" />
						<p class="invalid-feedback" style="display: block;" :style="{visibility: passwordStyle}">必须输入密码</p>
					</div>
					<div class="form-group">
						<button @click="login" type="button" class="btn btn-success input-width d-block mx-auto">登录</button>
					</div>
				</form>
			</div>
		</div><!-- 登录页面 -->

		<!-- 弹出对话框 -->
		<div id="modal-window" class="modal">
			<div class="modal-dialog modal-dialog-centered">
				<div class="modal-content">
					<div class="modal-header" style="background-color: #26A69A; padding: 10px 1rem;">
						<h6 class="modal-title text-white">系统提示</h6>
					</div>
					<div class="modal-body">
						<p class="text-danger">{{modalMessage}}</p>
					</div>
					<div class="modal-footer">
						<template v-if="modalType">
							<button v-for="(value, name) in modalType" type="button" class="btn btn-primary btn-sm"
									data-bs-dismiss="modal" @click="onModalClose(value)">{{name}}</button>
						</template>
						<button v-else type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @click="onModalClose(true)">关闭</button>
					</div>
				</div>
			</div>
		</div><!-- 弹出对话框 -->

		<!-- 编辑对话框 -->
		<div id="modal-edit" class="modal">
			<div class="modal-dialog modal-dialog-centered">
				<div class="modal-content">
					<div class="modal-header" style="background-color: #26A69A; padding: 10px 1rem;">
						<h6 class="modal-title text-white">数据编辑</h6>
					</div>
					<div class="modal-body">
						<div class="row align-items-center m-2">
							<div class="col-auto">
								<label for="edit-title" class="edit-label-width">标题</label>
							</div>
							<div class="col">
								<input id="edit-title" v-model="editRecord.title" @keyup.enter="editNextFocus"
										class="form-control edit-ctrl-width" type="text" placeholder="请输入标题" autofocus="autofocus" />
							</div>
						</div>
						<div class="row align-items-center m-2">
							<div class="col-auto">
								<label for="edit-user" class="edit-label-width">用户名</label>
							</div>
							<div class="col">
								<input id="edit-user" v-model="editRecord.user" @keyup.enter="editNextFocus"
										class="form-control edit-ctrl-width" type="text" placeholder="请输入用户名" autofocus="autofocus" />
							</div>
						</div>
						<div class="row align-items-center m-2">
							<div class="col-auto">
								<label for="edit-pass" class="edit-label-width">密码</label>
							</div>
							<div class="col">
								<input id="edit-pass" v-model="editRecord.pass" @keyup.enter="editNextFocus"
										class="form-control edit-ctrl-width" type="text" placeholder="请输入密码" autofocus="autofocus" />
							</div>
						</div>
						<div class="row align-items-center m-2">
							<div class="col-auto">
								<label for="edit-url" class="edit-label-width">URL</label>
							</div>
							<div class="col">
								<input id="edit-url" v-model="editRecord.url" @keyup.enter="editNextFocus"
										class="form-control edit-ctrl-width" type="text" placeholder="请输入URL" autofocus="autofocus" />
							</div>
						</div>
						<div class="row align-items-center m-2">
							<div class="col">
								<textarea  id="edit-memo" v-model="editRecord.memo" 
										class="form-control edit-ctrl-width" type="text" placeholder="请输入备注" rows="5"></textarea>
							</div>
						</div>
					</div>
					<div class="modal-footer">
						<button type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @click="editSubmit">确认</button>
						<button type="button" class="btn btn-sm" data-bs-dismiss="modal">取消</button>
					</div>
				</div>
			</div>
		</div><!-- 弹出对话框 -->

	</div><!-- app -->

	<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
	<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.4/vue.min.js"></script>

	<!-- <script src="js/bootstrap.bundle.min.js"></script> -->
	<!-- <script src="js/vue.min.js"></script> -->
	<script src="js/web_hack.js"></script>

	<script>

		async function API(url, params) {
			const res = await apiPost(url, params)
			if (res.status == 401) {
				vm.showPage = "login"
				return null
			}
			if (res.status == 404) {
				vm.showModal("接口不存在：" + url)
				return null
			}
			if (res.json.code) {
				vm.showModal("错误代码：{}，错误消息：{}".format(res.json.code, res.json.message))
				return null
			}
			return res
		}

		const defaultRecord = {title: null, user: null, pass: null, url: null, memo: null}

		const vm = new Vue({
			el: '#app',

			data() { return {
				// global
				showPage: 'home',	// 页面切换变量
				modalMessage: '',	// 弹出消息框的显示内容
				modalType: null,    // 弹出消息框类型 Ok / YesNo
				
				// home
				findStr: '',
				records: [],
				editRecord: {...defaultRecord},

				// login
				username: '',
				password: '',
				usernameChecked: true,
				passwordChecked: true,

			}},

			created() {
				this.showPage = document.cookie ? 'home' : 'login'
			},

			mounted() {
				this.myModal = new bootstrap.Modal(document.getElementById('modal-window'))
				this.editModal = new bootstrap.Modal(document.getElementById('modal-edit'))
			},

			computed: {
				usernameStyle: function () { return this.usernameChecked ? 'hidden' : 'visible' },
				passwordStyle: function () { return this.passwordChecked ? 'hidden' : 'visible' },
			},

			methods: {
				// 回车按键事件，跳转到下一个输入焦点
				nextFocus() {
					const next = document.activeElement.parentElement.nextElementSibling.firstElementChild
					next && next.focus()
				},

				// 弹出对话框函数
				async showModal(message, modalType) {
					this.modalMessage = message
					this.modalType = modalType
					return new Promise((resolve, reject) => {
						this.myModal.show()
						this.modalCallback = (val) => resolve(val)
					})
				},

				// 弹出对话框回调函数
				onModalClose(val) {
					if (this.modalCallback) this.modalCallback(val)
				},

				// 登录提交事件
				async login() {
					// 输入校验
					this.usernameChecked = !!this.username
					this.passwordChecked = !!this.password
					if (!this.username || !this.password) return
					// 登录
					const res = await API('/api/login', {user: this.username, pass: this.password})
					if (res) {
						this.showPage = 'home'
						this.username = ''
						this.password = ''
					}
				},

				// 退出登录
				logout() {
					document.cookie = ''
					this.records = null
					this.showPage = 'login'
				},

				// 查找
				async search() {
					// 登录
					const s = this.findStr.trim()
					const res = await API('/api/list', s ? {s} : undefined)
					if (res)
						this.records = res.json.data.records
				},

				edit(record) {
					this.editRecord = {...defaultRecord, ...record}
					this.editModal.show()
				},

				async editSubmit() {
					const res = await API('/api/post', this.editRecord)
					if (res) {
						const id = res.json.data.id
						const rs = this.records
						for (const i in rs) {
							if (rs[i].id == id) {
								Vue.set(rs, i, {...this.editRecord})
								return
							}
						}
						const v = {...this.editRecord, id}
						this.records.push(v)
					}
				},

				async del() {
					const ids = []
					for (const v of this.records)
						if (v.checked) ids.push(v.id)
					if (!ids.length) return
					const b = await this.showModal("将要删除所选记录，是否继续？", {"是": true, "否": false})
					if (b)
						API('/api/del', {ids})
				},

				// 回车按键事件，跳转到下一个输入焦点
				editNextFocus() {
					const f = document.activeElement.parentElement.parentElement.nextElementSibling.firstElementChild
					const next = f.nextElementSibling
					const elem = next ? next.firstElementChild : f.firstElementChild
					if (elem) elem.focus()
				},
			}
		}) // vue end

  </script>
</body>

</html>